import { ElButton, ElConfigProvider } from "element-plus";
import { Observable, Subject, Subscriber } from "rxjs";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import { Component, h, render } from "vue";
export type PopOption<T> = {
  component?: Component;
  title?: string;
  /**
   * | `sm` | `300` |
   * | `md` | `600` |
   * | `lg` | `900` |
   * | `xl` | `1200` |
   */
  size?: "sm" | "md" | "lg" | "xl" | number;
  /**
   * 底部是否显示默认显示
   */
  footer?: boolean;
  noFooter?: boolean;
  record?: Record<string, any>;
  i?: Record<string, any>;
  popOption?: Partial<T>;
};
export abstract class Base<O> {
  private cls = "drawer_dailog";
  protected option: PopOption<O>;
  protected noStc = false;
  protected comp: any;
  private sub: Subscriber<unknown>;
  protected openSub = new Subject();
  private obs: Observable<unknown>;
  protected abstract getPop(): Component;
  protected abstract closePop(destory?: boolean): void;
  constructor(option: PopOption<O>, stc?: boolean) {
    this.option = option;
    this.noStc = !!stc;
    this.createComponent();
  }

  of() {
    return this.obs;
  }

  protected get bodyElement() {
    return document.querySelector("body") as HTMLElement;
  }

  private createComponent() {
    this.obs = new Observable(sub => {
      if (!this.comp) {
        const element = document.createElement("div");
        element.classList.add(this.cls);
        this.comp = this.getRender();
        render(this.comp, element);
        this.bodyElement.appendChild(element);
        this.sub = sub;
      }
    });
  }

  private getRender() {
    const {
      component,
      footer = true,
      size = "lg",
      title = "",
      popOption = {},
      noFooter = false,
      ...arg
    } = this.option;

    return h(
      this.getPop(),
      {
        key: Date.now(),
        style: {
          width: this.getSize(size) + "px"
        },
        title,
        closeOnPressEscape: false,
        closeOnClickModal: false,
        ...popOption,
        size: this.getSize(size),
        modelValue: true
      },
      {
        default: () => [
          h(ElConfigProvider, { locale: zhCn }, () => [
            component
              ? h(component, {
                  helper: this,
                  openSub: this.openSub,
                  i: {},
                  ...arg
                })
              : ""
          ])
        ],
        footer: () =>
          noFooter
            ? []
            : [
                h(
                  "div",
                  {
                    style: {
                      flex: "auto",
                      height: "31px"
                    }
                  },
                  {
                    default: () => [
                      footer
                        ? h(
                            ElButton,
                            {
                              onClick: () => {
                                this.closePop();
                              }
                            },
                            () => "取消"
                          )
                        : "",
                      footer
                        ? h(
                            ElButton,
                            {
                              type: "primary",
                              onClick: () => {
                                console.log("保存了");
                              }
                            },
                            () => "保存"
                          )
                        : ""
                    ]
                  }
                )
              ]
      }
    );
  }

  private getSize(size: string | number) {
    return (
      {
        sm: 300,
        md: 600,
        lg: 900,
        xl: 1200
      }?.[size] || size
    );
  }

  open() {
    if (this.comp?.component?.proxy) {
      this.comp.component.proxy.visible = true;
      if (this.openSub.observed) {
        this.openSub.next("");
      }
    }
  }

  close(data?: unknown, destory = false) {
    if (data && this.sub) {
      this.sub.next(data);
    }
    this.closePop(destory);
  }
}
